package org.gthelper.order;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.gthelper.security.Iidentity;

/**
 * OrderBuilder
 * @author pig
 * 按顺序添加参数并对其签名后发送到指定的OutputStream中
 */
public class OrderBuilder
{
	public Iidentity ider = null;
	public int order = Header.OD_NONEORDER;
	public String charset = "UTF-8";
	private ByteArrayOutputStream orderBuf;
	private DataOutputStream dataout;
	
	/**
	 * 使用默认的编码格式和自定义的命令与签名类设置Builder
	 * @param order
	 * @param ider
	 */
	public void set(int order,Iidentity ider)
	{
		this.set(order,ider,"UTF-8");
	}
	
	/**
	 * 使用自定义的编码格式、命令与签名类设置Builder
	 * @param order
	 * @param ider
	 */
	public void set(int order,Iidentity ider,String charset)
	{
		this.order = order;
		this.ider = ider;
		this.charset = charset;
		this.orderBuf = new ByteArrayOutputStream();
		this.dataout = new DataOutputStream(orderBuf);
	}
	
	/**
	 * 清理Builder以重新使用
	 * @throws IOException
	 */
	public void clear() throws IOException
	{
		this.ider = null;
		this.order = -1;
		this.charset = "UTF-8";
		this.orderBuf.reset();
		this.orderBuf.close();
		this.orderBuf = new ByteArrayOutputStream();
		this.dataout = new DataOutputStream(orderBuf);
	}
	
	/**
	 * 签名后将请求写入指定流
	 * @param out 指定输出流
	 * @param privateKey 用于签名的私钥
	 * @throws Exception
	 */
	public void signNWriteTo(OutputStream out,byte[] privateKey) throws Exception
	{
		DataOutputStream dataOutput = new DataOutputStream(out);
		dataout.flush();
		byte[] orderdata = this.orderBuf.toByteArray();
		dataOutput.writeLong(4);
		dataOutput.writeInt(this.order);
		dataOutput.writeLong(orderdata.length);
		dataOutput.write(orderdata);
		if((this.order!=Header.OD_ASKFORLOGIN)&&(this.order!=Header.OD_ASKREG)&&(this.order!=Header.OD_LOGIN)&&(this.order!=Header.OD_REG))
		{
			byte[] sign = this.ider.sign(orderdata, privateKey);
			dataOutput.writeLong(sign.length);
			dataOutput.write(sign);
		}
		dataOutput.flush();
		
	}
	
	/**
	 * 添加参数
	 * @param param
	 * @throws IOException
	 */
	public void appendParam(byte[] param) throws IOException
	{
		dataout.writeLong(param.length);
		dataout.write(param);
	}
	
	/**
	 * 添加参数
	 * @param param
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	public void appendParam(String param) throws UnsupportedEncodingException, IOException
	{
		appendParam(param.getBytes(charset));
	}
	
	/**
	 * 添加参数
	 * @param param
	 * @throws IOException
	 */
	public void appendParam(int param) throws IOException
	{
		dataout.writeLong(4);
		dataout.writeInt(param);
	}
	
	/**
	 * 添加参数
	 * @param param
	 * @throws IOException
	 */
	public void appendParam(long param) throws IOException
	{
		dataout.writeLong(8);
		dataout.writeLong(param);
	}
	
	/**
	 * 添加参数
	 * @param param
	 * @throws IOException
	 */
	public void appendParam(float param) throws IOException
	{
		dataout.writeLong(4);
		dataout.writeFloat(param);
	}
	
	/**
	 * 添加参数
	 * @param param
	 * @throws IOException
	 */
	public void appendParam(double param) throws IOException
	{
		dataout.writeLong(8);
		dataout.writeDouble(param);
	}
	
	
}